package com.jfinal.ext.generator;

import com.jfinal.kit.StrKit;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

/**
 * @author fupan
 * @description validator 生成器  建议在表中添加字段备注remarks
 * @create 2017-08-21 14:46
 **/
public class ValidatorGenerator {
    protected String packageTemplate = "package %s.%s;%n%n";
    protected String importTemplate = "import com.jfinal.core.Controller;%n"
            + "import com.jfinal.validate.Validator;%n%n"
            + "import %s.%s.%s;%n%n";
    protected String classDefineTemplate = "/**%n" + " * Validator, Generated by Robot on %s.%n" + " */%n"
            + "public class %sValidator extends Validator {%n%n";
    protected String validateTemplateTitle = "\t@Override%n" + "\tprotected void validate(Controller c){%n";
    protected String validateTemplateContent = "\t\tvalidateRequiredString(\"%s\",\"%s\",\"%s不能为空\");%n";
    protected String handleErrorTemplate = "\t@Override%n" + "\tpublic void handleError(Controller c) {%n"
            + "\t\tc.keepModel(%s.class);%n"
            + "\t\tc.render(\"edit.html\");%n" + "\t}%n%n";
    protected String ValidatorPackageName;
    protected String ValidatorOutputDir;

    public ValidatorGenerator(String ValidatorPackageName, String ValidatorOutputDir) {
        if (StrKit.isBlank(ValidatorPackageName))
            throw new IllegalArgumentException("ValidatorPackageName can not be blank.");
        if (ValidatorPackageName.contains("/") || ValidatorPackageName.contains("\\"))
            throw new IllegalArgumentException("ValidatorPackageName error : " + ValidatorPackageName);
        if (StrKit.isBlank(ValidatorOutputDir))
            throw new IllegalArgumentException("ValidatorOutputDir can not be blank.");

        this.ValidatorPackageName = ValidatorPackageName;
        this.ValidatorOutputDir = ValidatorOutputDir;
    }


    public void generate(List<TableMeta> tableMetas) {
        System.out.println("Generate validator ...");
        for (TableMeta tableMeta : tableMetas)
            genValidatorContent(tableMeta);
        wirtToFile(tableMetas);
    }

    protected void genValidatorContent(TableMeta tableMeta) {
        StringBuilder ret = new StringBuilder();
        genPackage(tableMeta, ret);
        genImport(tableMeta,ret);
        genClassDefine(tableMeta, ret);
        genValidateMethod(tableMeta, ret);
        genHandleErrorMethod(tableMeta, ret);
        ret.append(String.format("}%n"));
        tableMeta.validatorContent = ret.toString();
    }

    protected void genPackage(TableMeta tableMeta, StringBuilder ret) {
        ret.append(String.format(packageTemplate, ValidatorPackageName, "validator"));
    }

    protected void genImport(TableMeta tableMeta,StringBuilder ret) {
        ret.append(String.format(importTemplate,ValidatorPackageName, "model", tableMeta.modelName));
    }

    protected void genClassDefine(TableMeta tableMeta, StringBuilder ret) {
        ret.append(String.format(classDefineTemplate, Constants.DATE_TIME, tableMeta.modelName));
    }

    protected void genValidateMethod(TableMeta tableMeta, StringBuilder ret) {
        ret.append(String.format(validateTemplateTitle));
        for(ColumnMeta columnMeta:tableMeta.getIsNotNull()){
            //非主键
            if(!columnMeta.isPrimaryKey.equalsIgnoreCase("PRI") ){
                String remarks=StrKit.isBlank(columnMeta.remarks)?columnMeta.name:columnMeta.remarks;
                ret.append(String.format(validateTemplateContent, StrKit.firstCharToLowerCase(tableMeta.modelName)+"."+columnMeta.name, columnMeta.name + "Msg", remarks));
            }
        }
        ret.append(String.format("\t}%n%n"));
    }

    protected void genHandleErrorMethod(TableMeta tableMeta, StringBuilder ret) {
        ret.append(String.format(handleErrorTemplate, tableMeta.modelName));
    }

    protected void wirtToFile(List<TableMeta> tableMetas) {
        try {
            for (TableMeta tableMeta : tableMetas)
                wirtToFile(tableMeta);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 若 model 文件存在，则不生成，以免覆盖用户手写的代码
     */
    protected void wirtToFile(TableMeta tableMeta) throws IOException {
        File dir = new File(ValidatorOutputDir + File.separator + "validator" + File.separator);
        if (!dir.exists())
            dir.mkdirs();

        String target = ValidatorOutputDir + File.separator + "validator" + File.separator + File.separator
                + tableMeta.modelName + "Validator.java";

        File file = new File(target);
        if (file.exists()||!tableMeta.validatorInIt) {
            return; // 若 Model 存在，不覆盖 表中没有不允许为null的值，不生成
        }
        FileWriter fw = new FileWriter(file);
        try {
            fw.write(tableMeta.validatorContent);
        } finally {
            fw.close();
        }
    }
}
